package com.starinside.wp.foundation.exception;

import com.starinside.wp.foundation.model.ErrorCode;
import com.starinside.wp.foundation.model.StatusResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartException;

import javax.persistence.EntityNotFoundException;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

/**
 * *******************************
 * Created by Tim.
 * form com.matt
 * on 2017/6/2
 * *******************************
 */
@RestControllerAdvice(basePackages = {"com.starinside", "com.tuo51", "com.matt", "com.dotflat"})
@Slf4j
public class GlobalExceptionHandler {

    @Value("${spring.profiles.active}")
    String env;

    @ExceptionHandler(MissingServletRequestParameterException.class)
    public StatusResponse parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
        log.error("", e);
        return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, "请求参数 " + e.getParameterName() + " 不能为空");
    }

    /**
     * 缺少请求体异常处理器
     *
     * @param e 缺少请求体异常
     * @return ResponseResult
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public StatusResponse parameterBodyMissingExceptionHandler(HttpMessageNotReadableException e) {
        log.error("", e);
        return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK,   "参数体不能为空");
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public StatusResponse paramExceptionHandler(MethodArgumentNotValidException e) {
        BindingResult exceptions = e.getBindingResult();
        // 判断异常中是否有错误信息，如果存在就使用异常中的消息，否则使用默认消息
        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                // 这里列出了全部错误参数，按正常逻辑，只需要第一条错误即可
                FieldError fieldError = (FieldError) errors.get(0);
                return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, fieldError.getDefaultMessage());
            }
        }
        return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, "请求参数错误");
    }


    @ExceptionHandler(BindException.class)
    public StatusResponse handlerNotValidException(BindException exception) {
        BindingResult exceptions = exception.getBindingResult();
        // 判断异常中是否有错误信息，如果存在就使用异常中的消息，否则使用默认消息
        if (exceptions.hasErrors()) {
            List<ObjectError> errors = exceptions.getAllErrors();
            if (!errors.isEmpty()) {
                // 这里列出了全部错误参数，按正常逻辑，只需要第一条错误即可
                FieldError fieldError = (FieldError) errors.get(0);
                return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, fieldError.getField() + fieldError.getDefaultMessage());
            }
        }
        return StatusResponse.error(ErrorCode.PARAM_CAN_NOT_BLANK, "请求参数错误");
    }

    @ExceptionHandler(Exception.class)
    @ResponseBody //在返回自定义相应类的情况下必须有，这是@ControllerAdvice注解的规定
    public StatusResponse exceptionHandler(RuntimeException e, HttpServletResponse response) {
        e.printStackTrace();

        if (e instanceof BusinessException)
            return StatusResponse.error(((BusinessException) e).getErrorCode(), e.getMessage());
        else if (e instanceof MultipartException)
            return StatusResponse.error(ErrorCode.FILE_SIZE_MORE_THAN_LIMIT, "文件过大！");
        else if (e instanceof EntityNotFoundException)
            return StatusResponse.error(ErrorCode.MATERIAL_NOT_EXIST, "对象不存在！");

        if(env.equals("dev"))
            return StatusResponse.error(ErrorCode.UNDEFINED,e.getMessage());
        else
            return StatusResponse.undefined();
    }
}
